package SquarePackage;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Raw;

import Border.Border;
import Border.Door;
import Border.Wall;
/** class representing a rock, this is square which is always surrounded completetly by borders. 
 * Its temperature depends on the temperature of the surrounding squares or is set to zero.
 * Its humidity is always zero and it does not have doots
 * @invar	this.getTemperature == average of the temperatures of the surrounding squares
 * 			|this.getTemperature == for each square (attached to each border in this.getBorders()
 * 			|which is not this square):
 * 			|add getTemperature() if(no more squares are available) divide by this.getNumberOfNeighBours()
 * @invar	this.humidity = BIGDECIMAL.ZERO
 * @invar	for each Border in this.getBorders() Border.getClass()==Wall.class
 * @invar	for each Border in this.getBorders() Border !instanceof Door
 * @invar   amount of Doors<= MAX_AMOUNT_OF_DOORS
 * @invar	amount of Borders = MAX_NUMBER_BORDERS
 * @invar	all the borders are Walls |onlyWallBorders(getBorders())
 * @author 	Florian en Bert 
 * @version	1.1
 */

public class Rock extends Square {
	/**
	 * Constructor for Rocks which corresponds to the appropriate invariants
	 * @effect	presetBorders
	 * 			makes sure all the Borders are Walls
	 */
	public Rock(){
		super();
		this.humidity = BigDecimal.ZERO;
		this.humidity = humidity.setScale(2,BigDecimal.ROUND_HALF_UP);
		this.temperature = new Temperature(0);
	}
	/**
	 * Presetter to make sure that all the borders are walls.
	 */
	protected void preSetBorders() {
		borders = new EnumMap<Direction, Border>(Direction.class);
        for (Direction direction : Direction.values()){
            Wall newWall = new Wall(this,direction);    
        	borders.put(direction,newWall);
        	newWall.setSquare(this);
        }
	}
	/**
	 * method which overrides getHumidity from square and will always return 0 as we can not change the humidity from rocks
	 * @return	BigDecimal
	 * 			Zero amount of Humidity
	 */
	@Override
	public BigDecimal getHumidity(){
		return BigDecimal.ZERO;
	}
    /**
     * Check whether this rock can have the given border as a border.
     * @return False if the border is not a Wall or if the other contraints from square are not valid
     *        | if(! border instanceof Wall || !super.canHaveAsBorder(border,direction)
     *        |       result == false.
     * @param	Border
     * 			the Border object to check
     * @param	Direction
     * 
     */
	@Override
    public boolean canHaveAsBorder(Border border,Direction direction){
            return super.canHaveAsBorder(border,direction) && (border instanceof Wall);
    }
    /**
     * Check whether this rock has proper borders attached to it.
     * 
     * @return  Boolean
     * 			False if common rules are broken or if the Specific Rock constraints are broken(INVAR°
     */
    @Override
    public boolean hasProperBorders(Map<Direction, Border> tempBorders) {
            return (super.hasProperBorders(tempBorders))&& (numberOfBorders(tempBorders) == 6)&&(onlyWallBorders(tempBorders));
    }
    /**
     * this method checks whether the square contains only walls
     * @param borders the map with the direction and the border for that direction
     * @return true if the square has only walls as border
     *              | for each border in borders.values()
     *              | if(border == null || !(Wall.class.isInstance(border)))
     *              | then result== false
     */
    private boolean onlyWallBorders(Map<Direction, Border> borders) {
            for(Border border:borders.values()){
                    if(!(Wall.class.isInstance(border)))
                    return false;
            }
            return true;
 
    }
    /**
     * Constant for the max amount of doors a rock can have.
     */
    private final static int MAX_AMOUNT_OF_DOORS = 0;
    /**
     * get max amount of Doors
     * @return MAX_AMOUNT_OF_DOORS
     */
	@Override
	public int getMaxAmountOfDoors() {
		return MAX_AMOUNT_OF_DOORS;
	}
    /**
     * Variable registering the maximal amount of borders a rock can have.
     */
    private final static int MAX_NUMBER_BORDERS = 6;
	/**
	 * get max amount of Borders
	 * @return MAX_NUMBER_BORDERS
	 */
	@Override
	public int getMaxNumberBorders() {
		return MAX_NUMBER_BORDERS;
	}

	
	/**
	 * method to check how many of the neigbouring squares are Rockx
	 * @return int
	 * 			the number of Rocks surrounding this rock
	 */
	private int getNumberOfRockNeighbours(){
		int amount = 0;
		for(Border border : borders.values()){
			if(border.getOtherSquare(this) instanceof Rock){
				amount++;
			}
		}
		return amount;

	 * Borders can not be removed from rocks unless they are terminated
	 */
	@Override
	public void removeBorder(Direction direction) {
	     if((this.isTerminated())){
	    	 super.removeBorder(direction);
	     }
	}
	/**
	 * Borders can not be removed from rocks unless they are terminated
	 */
	@Override
	public void removeBorder(Border tempBorder) {
	     if((this.isTerminated())){
	    	 super.removeBorder(tempBorder);
	     }
	}
	/**
	 * Borders can not be removed from rocks unless they are terminated
	 */
	@Override
	public void removeBorders(Direction... directions){
		if((this.isTerminated())){
	    	 super.removeBorders(directions);
	     }
	}
    /**
     * Replace the first given border with the second given border.
     * 
     * @param       currentBorder
     *                      The border that must be replaced.
     * @param       newBorder
     *                      The border to replace the old border with.
     * @post        This square no longer references oldBorder as one of its borders
     */
    public void replaceBorderWith(Border currentBorder, Border newBorder){
    	if(canHaveAsBorder(newBorder,getBorderDirection(currentBorder))&& hasBorder(getBorderDirection(currentBorder)) && currentBorder.hasSquare(this)){
    		Direction direction = getBorderDirection(currentBorder);
    		borders.remove(direction);
    		borders.put(direction,newBorder);
    	}
    }
}


